// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

package utils

import (
	"crypto/rand"
	"math/big"
)

// CryptoRandomInt returns a crypto random integer between 0 and limit, inclusive
// Copied from https://github.com/go-gitea/gitea/blob/main/modules/util/util.go#L121-L127
func CryptoRandomInt(limit int64) (int64, error) {
	rInt, err := rand.Int(rand.Reader, big.NewInt(limit))
	if err != nil {
		return 0, err
	}
	return rInt.Int64(), nil
}

const alphanumericalChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

// CryptoRandomString generates a crypto random alphanumerical string, each byte is generated by [0,61] range
// Copied from https://github.com/go-gitea/gitea/blob/main/modules/util/util.go#L131-L143
func CryptoRandomString(length int64) (string, error) {
	buf := make([]byte, length)
	limit := int64(len(alphanumericalChars))
	for i := range buf {
		num, err := CryptoRandomInt(limit)
		if err != nil {
			return "", err
		}
		buf[i] = alphanumericalChars[num]
	}
	return string(buf), nil
}

// CryptoRandomBytes generates `length` crypto bytes
// This differs from CryptoRandomString, as each byte in CryptoRandomString is generated by [0,61] range
// This function generates totally random bytes, each byte is generated by [0,255] range
// Copied from https://github.com/go-gitea/gitea/blob/main/modules/util/util.go#L145-L152
func CryptoRandomBytes(length int64) ([]byte, error) {
	buf := make([]byte, length)
	_, err := rand.Read(buf)
	return buf, err
}
